unit DataSetSerializeHelper;

interface

uses superobject, DB, LanguageTypes;

type
  TDataSetSerializeHelper = class
  private
    Fsource: TDataSet;
  public
    /// <summary>
    ///   Creates a JSON object with the data from the current record of DataSet.
    /// </summary>
    /// <param name="AOnlyUpdatedRecords">
    ///   Exports only inserted, modified and deleted data from childs dataset.
    /// </param>
    /// <param name="AChildRecords">
    ///   Exports only childs records from child datasets.
    /// </param>
    /// <returns>
    ///   Returns a JSON object containing the record data.
    /// </returns>
    /// <remarks>
    ///   Invisible fields will not be generated.
    /// </remarks>
    function ToJSONObject(const AOnlyUpdatedRecords: Boolean = False; const
      AChildRecords: Boolean = True): ISuperObject;
    /// </summary>
    /// <param name="AOnlyUpdatedRecords">
    ///   Exports only inserted, modified and deleted data from childs dataset.
    /// </param>
    /// <param name="AChildRecords">
    ///   Exports only childs records from child datasets.
    /// </param>
    /// <returns>
    ///   Returns a JSONArray with all records from the DataSet.
    /// </returns>
    /// <remarks>
    ///   Invisible fields will not be generated.
    /// </remarks>
//    function ToJSONArray(const AOnlyUpdatedRecords: Boolean = False; const AChildRecords: Boolean = True): TJSONArray;
    function ToJSONArray(const AOnlyUpdatedRecords: Boolean = False; const
      AChildRecords: Boolean = True): ISuperObject;
    ///   Responsible for exporting the structure of a DataSet in JSON Array format.
    /// </summary>
    /// <returns>
    ///   Returns a JSON array with all fields of the DataSet.
    /// </returns>
    /// <remarks>
    ///   Invisible fields will not be generated.
    /// </remarks>
//    function SaveStructure: TJSONArray;
    function SaveStructure: ISuperObject;
    ///   Loads fields from a DataSet based on a JSONArray.
    /// </summary>
    /// <param name="AJSONArray">
    ///   Refers to JSON with field specifications.
    /// </param>
    /// <param name="AOwns">
    ///   Destroy JSON in the end.
    /// </param>
//    procedure LoadStructure(const AJSONArray: TJSONArray; const AOwns: Boolean = True); overload;
    procedure LoadStructure(const AJSONArray: TSuperArray; const AOwns: Boolean =
      True); overload;
    ///   Loads fields from a DataSet based on a JSON (string format).
    /// </summary>
    /// <param name="AJSONString">
    ///   Refers to JSON with field specifications.
    /// </param>
    procedure LoadStructure(const AJSONString: string); overload;
    /// <summary>
    ///   Loads the DataSet with data from a JSON object.
    /// </summary>
    /// <param name="AJSONObject">
    ///   Refers to JSON that you want to load.
    /// </param>
    /// <param name="AOwns">
    ///   Destroy JSON in the end.
    /// </param>
    /// <remarks>
    ///   Only the keys that make up the DataSet field list will be loaded. The JSON keys must have the same name as the
    ///   DataSet fields. It's not case-sensitive.
    /// </remarks>
//    procedure LoadFromJSON(const AJSONObject: TJSONObject; const AOwns: Boolean = True); overload;
    procedure LoadFromJSON(const AJSONObject: ISuperObject; const AOwns: Boolean =
      True); overload;
    ///   Loads the DataSet with data from a JSON array.
    /// </summary>
    /// <param name="AJSONArray">
    ///   Refers to JSON that you want to load.
    /// </param>
    /// <param name="AOwns">
    ///   Destroy JSON in the end.
    /// </param>
    /// <remarks>
    ///   Only the keys that make up the DataSet field list will be loaded. The JSON keys must have the same name as the
    ///   DataSet fields. It's not case-sensitive.
    /// </remarks>
//    procedure LoadFromJSON(const AJSONArray: TJSONArray; const AOwns: Boolean = True); overload;
    procedure LoadFromJSON(const AJSONArray: TSuperArray; const AOwns: Boolean =
      True); overload;
    ///   Loads the DataSet with data from a JSON (string format).
    /// </summary>
    /// <param name="AJSONString">
    ///   Refers to JSON that you want to load.
    /// </param>
    /// <remarks>
    ///   Only the keys that make up the DataSet field list will be loaded. The JSON keys must have the same name as the
    ///   DataSet fields. It's not case-sensitive.
    /// </remarks>
    procedure LoadFromJSON(const AJSONString: string); overload;
    /// <summary>
    ///   Updates the DataSet data with JSON object data.
    /// </summary>
    /// <param name="AJSONObject">
    ///   Refers to JSON that you want to merge.
    /// </param>
    /// <param name="AOwns">
    ///   Destroy JSON in the end.
    /// </param>
//    procedure MergeFromJSONObject(const AJSONObject: TJSONObject; const AOwns: Boolean = True); overload;
    procedure MergeFromJSONObject(const AJSONObject: ISuperObject; const AOwns:
      Boolean = True); overload;
    ///   Updates the DataSet data with JSON object data (string format).
    /// </summary>
    /// <param name="AJSONString">
    ///   Refers to JSON that you want to merge.
    /// </param>
    procedure MergeFromJSONObject(const AJSONString: string); overload;
    /// <summary>
    ///   Responsible for validating whether JSON has all the necessary information for a particular DataSet.
    /// </summary>
    /// <param name="AJSONObject">
    ///   Refers to JSON that must be validated.
    /// </param>
    /// <param name="ALang">
    ///   Language used to mount messages.
    /// </param>
    /// <param name="AOwns">
    ///   Destroy JSON in the end.
    /// </param>
    /// <returns>
    ///   Returns a JSONArray with the fields that were not informed.
    /// </returns>
    /// <remarks>
    ///   Walk the DataSet fields by checking the required property.
    ///   Uses the DisplayLabel property to mount the message.
    /// </remarks>
//    function ValidateJSON(const AJSONObject: TJSONObject; const ALang: TLanguageType = enUS; const AOwns: Boolean = True): TJSONArray; overload;
    function ValidateJSON(const AJSONObject: ISuperObject; const ALang:
      TLanguageType = enUS; const AOwns: Boolean = True): ISuperObject; overload;
    /// </summary>
    /// <param name="AJSONString">
    ///   Refers to JSON that must be validated.
    /// </param>
    /// <param name="ALang">
    ///   Language used to mount messages.
    /// </param>
    /// <returns>
    ///   Returns a JSONArray with the fields that were not informed.
    /// </returns>
    /// <remarks>
    ///   Walk the DataSet fields by checking the required property.
    ///   Uses the DisplayLabel property to mount the message.
    /// </remarks>
//    function ValidateJSON(const AJSONString: string; const ALang: TLanguageType = enUS): TJSONArray; overload;
    function ValidateJSON(const AJSONString: string; const ALang: TLanguageType =
      enUS): ISuperObject; overload;
    property Dest: Tdataset read Fsource write FSource;
  end;

implementation

uses SysUtils, DataSetSerializeDSImpl, DataSetSerializeJSONImpl, StrUtils;

function TDataSetSerializeHelper.ToJSONArray(const AOnlyUpdatedRecords: Boolean = False; const
  AChildRecords: Boolean = True): IsuperObject;
var
  LDataSetSerialize: TDataSetSerialize;
begin
  LDataSetSerialize := TDataSetSerialize.Create(Fsource, AOnlyUpdatedRecords, AChildRecords);
  try
    Result := LDataSetSerialize.ToJSONArray;
  finally
    LDataSetSerialize.Free;
  end;
end;

function TDataSetSerializeHelper.ToJSONObject(const AOnlyUpdatedRecords:
  Boolean = False; const AChildRecords: Boolean = True): ISuperObject;
var
  LDataSetSerialize: TDataSetSerialize;
begin
  LDataSetSerialize := TDataSetSerialize.Create(Fsource, AOnlyUpdatedRecords, AChildRecords);
  try
    Result := LDataSetSerialize.ToJSONObject;
  finally
    LDataSetSerialize.Free;
  end;
end;

function TDataSetSerializeHelper.SaveStructure: ISuperObject;
var
  LDataSetSerialize: TDataSetSerialize;
begin
  LDataSetSerialize := TDataSetSerialize.Create(Fsource);
  try
    Result := LDataSetSerialize.SaveStructure;
  finally
    LDataSetSerialize.Free;
  end;
end;

function TDataSetSerializeHelper.ValidateJSON(const AJSONObject: ISuperObject;
  const ALang: TLanguageType = enUS; const AOwns: Boolean = True): ISuperObject;
var
  LJSONSerialize: TJSONSerialize;
begin
  LJSONSerialize := TJSONSerialize.Create(AJSONObject, AOwns);
  try
    Result := LJSONSerialize.Validate(Fsource, ALang);
  finally
    LJSONSerialize.Free;
  end;
end;

procedure TDataSetSerializeHelper.LoadFromJSON(const AJSONArray: TSuperArray;
  const AOwns: Boolean = True);
var
  LJSONSerialize: TJSONSerialize;
begin
  LJSONSerialize := TJSONSerialize.Create(AJSONArray, AOwns);
  try
    LJSONSerialize.ToDataSet(Fsource);
  finally
    LJSONSerialize.Free;
  end;
end;

procedure TDataSetSerializeHelper.LoadFromJSON(const AJSONObject: ISuperObject;
  const AOwns: Boolean = True);
var
  LJSONSerialize: TJSONSerialize;
begin
  LJSONSerialize := TJSONSerialize.Create(AJSONObject, AOwns);
  try
    LJSONSerialize.ToDataSet(Fsource);
  finally
    LJSONSerialize.Free;
  end;
end;

procedure TDataSetSerializeHelper.LoadStructure(const AJSONArray: TSuperArray;
  const AOwns: Boolean = True);
var
  LJSONSerialize: TJSONSerialize;
begin
  LJSONSerialize := TJSONSerialize.Create(AJSONArray, AOwns);
  try
    LJSONSerialize.LoadStructure(Fsource);
  finally
    LJSONSerialize.Free;
  end;
end;

procedure TDataSetSerializeHelper.MergeFromJSONObject(const AJSONObject:
  ISuperObject; const AOwns: Boolean = True);
var
  LJSONSerialize: TJSONSerialize;
begin
  LJSONSerialize := TJSONSerialize.Create(AJSONObject, AOwns);
  try
    LJSONSerialize.Merge(Fsource);
  finally
    LJSONSerialize.Free;
  end;
end;

function TDataSetSerializeHelper.ValidateJSON(const AJSONString: string; const
  ALang: TLanguageType = enUS): ISuperObject;
begin
  if AnsiStartsStr('{', Trim(AJSONString)) then
    Result :=
      ValidateJSON(SO(AJSONString), ALang)
  else
    Result := TSuperObject.Create();
end;

procedure TDataSetSerializeHelper.LoadFromJSON(const AJSONString: string);
begin
  if AnsiStartsStr('{', Trim(AJSONString)) then
    LoadFromJSON(SO(AJSONString))
  else if AnsiStartsStr('[', Trim(AJSONString)) then
    LoadFromJSON(SO(AJSONString).AsArray);
end;

procedure TDataSetSerializeHelper.LoadStructure(const AJSONString: string);
begin
  if AnsiStartsStr('[', Trim(AJSONString)) then
    LoadStructure(SO(AJSONString).AsArray);
end;

procedure TDataSetSerializeHelper.MergeFromJSONObject(const AJSONString: string);
begin
  if AnsiStartsStr('{', Trim(AJSONString)) then
    MergeFromJSONObject(SO(AJSONString));
end;

end.
